package com.imooc.ad.mysql.dto;

import com.imooc.ad.mysql.constant.OpType;
import lombok.Data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

/**
 * 对resources中模板文件template.json进行解析
 * Template -> JsonTable -> TableTemplate -> ParseTemplate
 */
@Data
public class ParseTemplate {

    //数据库
    private String database;

    //各个表名及对应属性(层级/操作/字段)
    private Map<String, TableTemplate> tableTemplateMap = new HashMap<>();

    public static ParseTemplate parse(Template _template) {

        ParseTemplate template = new ParseTemplate();
        //获取数据库
        template.setDatabase(_template.getDatabase());

        //遍历各个表,Template:tableList -> JsonTable:table
        for (JsonTable table : _template.getTableList()) {

            String name = table.getTableName();
            Integer level = table.getLevel();

            //JsonTable数据封装到TableTemplate，JsonTable -> TableTemplate
            TableTemplate tableTemplate = new TableTemplate();
            tableTemplate.setTableName(name);
            tableTemplate.setLevel(level.toString());

            //填充当前类的tableTemplateMap <表名,对应属性>
            template.tableTemplateMap.put(name, tableTemplate);

            //新建TableTemplate的opTypeFieldSetMap，用于填充<操作类型,对应字段>
            Map<OpType, List<String>> opTypeFieldSetMap = tableTemplate.getOpTypeFieldSetMap();

            //遍历操作类型对应的列，并调用getAndCreateIfNeed方法填充opTypeFieldSetMap
            for (JsonTable.Column column : table.getInsert()) {
                getAndCreateIfNeed(
                        OpType.ADD, opTypeFieldSetMap, ArrayList::new
                ).add(column.getColumn());
            }
            for (JsonTable.Column column : table.getUpdate()) {
                getAndCreateIfNeed(
                        OpType.UPDATE, opTypeFieldSetMap, ArrayList::new
                ).add(column.getColumn());
            }
            for (JsonTable.Column column : table.getDelete()) {
                getAndCreateIfNeed(
                        OpType.DELETE, opTypeFieldSetMap, ArrayList::new
                ).add(column.getColumn());
            }
        }

        return template;
    }

    //map中按key操作类型OpType取值，取出操作属性opTypeFieldSetMap，不存在则new一个map并存入key并返回
    private static <T, R> R getAndCreateIfNeed(T key, Map<T, R> map, Supplier<R> factory) {
        return map.computeIfAbsent(key, k -> factory.get());
    }
}
